﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using CxExtension.Hashset;
using CxExtension;

public class Timer
{
	private uint id_count = 0;
	private HashSet<TimeData> times = new HashSet<TimeData>();
	private HashSet<TimeData> addlist = new HashSet<TimeData>();
	private HashSet<TimeData> dellist = new HashSet<TimeData>();
	private bool hasAdd;
	private bool isRuntime;
	private bool hasDel;
	public enum TimeState
	{

	}
	class TimeData
	{
		public uint id;
		public float usedtime;
		public float duration;
		public int repeatMax = 1;
		public int repeatCur = 0;
		public bool enable = true;
		public virtual bool Excute() { return true; }
	}
	class TimeData0:TimeData
	{
		public System.Action func;
		public override bool Excute()
		{
			if(func != null)
			{
				func();
			}
			return true;
		}
	}
	private uint generiteId()
	{
		id_count++;
		return id_count;
	}
	private TimeData Find(uint id)
	{
		return times.Find(item => item.id == id);
	}
	public uint AddTimer(float delay,System.Action func)
	{
		var d = AddTimer();
		d.duration = delay;
		d.func = func;
		return d.id;
	}
	private TimeData0 AddTimer()
	{
		var d = new TimeData0();
		Add0(d);
		return d;
	}
	public uint AddSchedule(float interval,int repeatMaxTimes,System.Action func)
	{
		var d = AddTimer();
		d.duration = interval;
		d.repeatMax = repeatMaxTimes;
		d.func = func;
		return d.id;
	}
	public void SetActive(uint id,bool b)
	{
		var t = Find(id);
		if(t != null)
		{
			t.enable = b;
		}
	}
	public void RemoveTimer(uint id)
	{
		var t = Find(id);
		if(isRuntime)
		{
			Delete_(t);
		}
		else
		{
			times.Remove(t);
		}
	}
	public void RemoveAll()
	{

	}
	public void ClearAll()
	{
		dellist.Clear();
		times.Clear();
		addlist.Clear();
	}
	public int count
	{
		get { return times.Count; }
	}
	private uint Add0(TimeData t)
	{
		var id = generiteId();
		t.id = id;
		if(isRuntime)
		{
			Add_(t);
		}
		else
		{
			times.Add(t);
		}
		return id;
	}
	private void Add_(TimeData t)
	{
		hasAdd = true;
		addlist.Add(t);
	}
	private void Delete_(TimeData t)
	{
		hasDel = true;
		dellist.Add(t);
	}
	private bool UpdateTime(TimeData t,float dt)
	{
		if(!t.enable) return false;
		if(t.usedtime >= t.duration)
		{
			t.Excute();
			t.repeatCur++;
			if(t.repeatCur >= t.repeatMax)
			{
				return true;
			}
			else
			{
				t.usedtime -= t.duration;
				return false;
			}
		}
		else
		{
			t.usedtime += dt;
			return false;
		}
	}
	public bool Update(float dt)
	{
		isRuntime = true;
		hasDel = false;
		foreach(var item in times)
		{
			if(UpdateTime(item,dt))
			{
				Delete_(item);
			}
		}
		isRuntime = false;
		times.Add(addlist,ref hasAdd);
		if(hasDel)
		{
			times.Remove(dellist,ref hasDel);
			if(times.Count == 0)
			{
				return false;
			}
			return true;
		}
		return true;
		/*if(hasAdd)
		{
			foreach(var item in addlist)
			{
				times.Add(item);
			}
			addlist.Clear();
		}
		if(hasDel)
		{
			foreach(var item in dellist)
			{
				times.Remove(item);
			}
			dellist.Clear();
		}*/
	}
}
